#ifndef EPUBDUKPT_DEVS_CRYPTO_HPP
#define EPUBDUKPT_DEVS_CRYPTO_HPP

SJR_NAMESPACE_BEGIN

class EpubCrypto final : public EpubCryptoBasic {
public:
  enum Mode {
    DesEcb  = 1,
    TdesEcb = 2,
  };

  explicit EpubCrypto(Mode mode) : mBasic() {
    switch (mode) {
      case DesEcb:
        mBasic = new EpubCryptoDes();
        break;
      case TdesEcb:
        mBasic = new EpubCryptoTdes();
        break;
      default:
        mBasic = nullptr;
        break;
    }
  }

  ~EpubCrypto() override {
    delete (mBasic);
  }

  template<class... Args>
  static auto createSchedule(Mode mode, Args... args) -> Schedule * {
    switch (mode) {
      case DesEcb:
        return new EpubCryptoDes::ScheduleDes(args...);
      case TdesEcb:
        return new EpubCryptoTdes::ScheduleTdes(args...);
      default:
        return nullptr;
    }
  }

  static void destroySchedule(Schedule *in) {
    delete (in);
  }

  auto blockSize(Schedule *key) -> int override {
    return (*mBasic).blockSize(key);
  }

  auto encrypt(Schedule *key, unsigned char const *in, unsigned char *out) -> bool override {
    return (*mBasic).encrypt(key, in, out);
  }

  auto decrypt(Schedule *key, unsigned char const *in, unsigned char *out) -> bool override {
    return (*mBasic).decrypt(key, in, out);
  }

private:
  EpubCryptoBasic *mBasic;
};

SJR_NAMESPACE_END

#endif//EPUBDUKPT_DEVS_CRYPTO_HPP
